package com.rockcent.service.impl;

import com.rockcent.common.common.BusinessException;
import com.rockcent.common.utils.DateUtils;
import com.rockcent.common.utils.GenNumUtils;
import com.rockcent.mall.lib.domain.MerchantRechargePayment;
import com.rockcent.mall.lib.domain.MerchantRechargePaymentFlow;
import com.rockcent.mall.lib.domain.enumclass.MerchantRechargePaymentStatus;
import com.rockcent.mall.lib.domain.enumclass.PaymentMethod;
import com.rockcent.mall.lib.dto.MerchantRechargeFlowDto;
import com.rockcent.mall.lib.repository.MerchantRechargePaymentFlowRepository;
import com.rockcent.mall.lib.repository.MerchantRechargePaymentRepository;
import com.rockcent.service.MerchantRechargeFlowSrv;
import com.rockcent.service.WechatRechargeService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;

/**
 * Created by hone on 17-3-29.
 */
@Service
public class WechatRechargeServiceImpl implements WechatRechargeService {

    private Logger log = LoggerFactory.getLogger(WechatRechargeServiceImpl.class);

    @Autowired
    private MerchantRechargePaymentRepository merchantRechargePaymentRepository;

    @Autowired
    private MerchantRechargePaymentFlowRepository merchantRechargePaymentFlowRepository;

    @Autowired
    private MerchantRechargeFlowSrv merchantRechargeFlowSrv;

    /**
     * 生成充值流水
     * @param rechargeAmount
     * @param mallId
     * @param merchantId
     * @param operatorId
     * @return
     */
    @Override
    public MerchantRechargePayment create(BigDecimal rechargeAmount, Long mallId, Long merchantId, Long operatorId) {
        MerchantRechargePayment merchantRechargePayment = null;
        if(rechargeAmount!=null && mallId!=null && merchantId!=null) {
            merchantRechargePayment = new MerchantRechargePayment();
            merchantRechargePayment.setRechargeAmount(rechargeAmount);
            merchantRechargePayment.setMallId(mallId);
            merchantRechargePayment.setMerchantId(merchantId);
            merchantRechargePayment.setOperatorId(operatorId);
            merchantRechargePayment.setSerialNum(String.valueOf(GenNumUtils.nextSid()));
            merchantRechargePayment.setPaymentMethod(PaymentMethod.NATIVE);
            merchantRechargePayment.setStatus(MerchantRechargePaymentStatus.WAITING);
            merchantRechargePayment = merchantRechargePaymentRepository.save(merchantRechargePayment);
        }
        return merchantRechargePayment;
    }

    /**
     * 生成成功支付流水
     * @param payId
     * @param payNo
     * @param transactionId
     * @param rechargeAmount
     * @param timeEnd
     */
    @Override
    public void createMerchantRechargeFlow(Long payId, String payNo, String transactionId, BigDecimal rechargeAmount, String timeEnd) {
        if(payId==null || rechargeAmount==null || StringUtils.isEmpty(payNo) || StringUtils.isEmpty(transactionId) || StringUtils.isEmpty(timeEnd)) {
            throw new BusinessException("createMerchantRechargeFlow params error");
        }
        MerchantRechargePayment merchantRechargePayment = merchantRechargePaymentRepository.getById(payId);
        if(merchantRechargePayment==null) {
            throw new BusinessException("createMerchantRechargeFlow merchantRechargePayment not found");
        }
        if(!payNo.equals(merchantRechargePayment.getSerialNum())) {
            throw new BusinessException("createMerchantRechargeFlow payNo not found");
        }
        if(merchantRechargePayment.getStatus().equals(MerchantRechargePaymentStatus.SUCCESS)) {
            throw new BusinessException("createMerchantRechargeFlow merchantRechargePayment has already pay success");
        }
        MerchantRechargePaymentFlow merchantRechargePaymentFlow = merchantRechargePaymentFlowRepository.findByMerchantRechargePaymentId(merchantRechargePayment.getId());
        if(merchantRechargePaymentFlow!=null) {
            throw new BusinessException("createMerchantRechargeFlow merchantRechargePaymentFlow has already exists");
        }
        MerchantRechargePaymentFlow flow = new MerchantRechargePaymentFlow();
        flow.setMallId(merchantRechargePayment.getMallId());
        flow.setMerchantId(merchantRechargePayment.getMerchantId());
        flow.setMerchantRechargePaymentId(merchantRechargePayment.getId());
        flow.setPaymentMethod(PaymentMethod.NATIVE);
        flow.setRechargeAmount(merchantRechargePayment.getRechargeAmount());
        flow.setStatus(MerchantRechargePaymentStatus.SUCCESS);
        merchantRechargePaymentFlowRepository.save(flow);

        MerchantRechargePaymentStatus businessStatus = MerchantRechargePaymentStatus.SUCCESS;
        try {
            MerchantRechargeFlowDto merchantRechargeFlowDto = new MerchantRechargeFlowDto();
            merchantRechargeFlowDto.setRechargeAmount(merchantRechargePayment.getRechargeAmount());
            merchantRechargeFlowDto.setSeqNo(merchantRechargePayment.getSerialNum());
            merchantRechargeFlowSrv.saveOnlineRecharge(merchantRechargeFlowDto, merchantRechargePayment.getMallId(), merchantRechargePayment.getMerchantId(), merchantRechargePayment.getOperatorId());
        } catch (Exception e) {
            businessStatus = MerchantRechargePaymentStatus.FAILED;
            log.error("======================>merchantRechargeFlowSrv saveOnlineRecharge failed:{}",e);
        }

        merchantRechargePayment.setBusinessStatus(businessStatus);
        merchantRechargePayment.setFinishDate(DateUtils.string2Date(timeEnd));
        merchantRechargePayment.setTransactionId(transactionId);
        merchantRechargePayment.setStatus(MerchantRechargePaymentStatus.SUCCESS);
        merchantRechargePaymentRepository.save(merchantRechargePayment);
    }

    @Override
    public MerchantRechargePayment findByNum(String payNo) {
        MerchantRechargePayment merchantRechargePayment = null;
        if(StringUtils.isNotEmpty(payNo)) {
            merchantRechargePayment = merchantRechargePaymentRepository.findBySerialNum(payNo);
        }
        return merchantRechargePayment;
    }
}
